
// 关闭ts检查
// @ts-nocheck
import { ChromeFilled, LikeOutlined, DislikeOutlined, WarningOutlined, CloseOutlined, CloudUploadOutlined, CopyOutlined, PaperClipOutlined, FileExcelTwoTone, FireOutlined, Html5Outlined, ReadOutlined, RocketOutlined, CaretRightOutlined, SyncOutlined, CheckCircleFilled } from '@ant-design/icons';
import FileExplorer from './components/FileExplorer';
import { Attachments, Bubble, Prompts, Sender, useXAgent, useXChat, Welcome } from '@ant-design/x';
import { css } from '@emotion/css';
import { Badge, Button, Divider, Flex, message, Modal, Segmented, Select, Space, Typography, Upload } from 'antd';
import DOMPurify from 'dompurify';
import ReactECharts from 'echarts-for-react';
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-dark.css'; // 选择一款主题
import markdownit from 'markdown-it';
import OpenAI from 'openai';
import React, { JSX, useEffect, useMemo, useState, useCallback, useRef } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import WT_icon from '../../assets/images/logo0402.svg';
import loading from '../../assets/images/loading.svg';
import renwu from '../../assets/images/renwu.svg';
import bianzu from '../../assets/images/bianzu.svg';
import shendusikao from '../../assets/images/loading.svg';
import thinkingIcon from '../../assets/images/thinkingIcon.svg';
import chevronDown from '../../assets/images/chevronDown.svg';
import { generateRandomNumber } from '../../utils/common';
import { generateHeaders, generateHeadersChat } from '../../utils/header';
import canvasDrawing from './canvasDrawing';
import ChooseSource from './chooseSource';
import './index.less';
const uuidv4 = require('uuid').v4;
import { useSearchParams } from 'react-router-dom';

// 添加类型定义
type ContentType = 'html' | 'text' | 'sql' | 'image' | 'chart' | 'code' | 'table' | 'think' | 'mcp' | 'loading' | `status@planing` | `plan@${number}@title` | `plan@${number}@content`;

interface AttachedFile {
    uid: string;
    name: string;
    status: 'done' | 'uploading' | 'error';
    type: string;
}
let agentLoading = false;
// 配置参数
const COMMON_APPID = 'dsjyybai';
const COMMON_APPKEY = 'bb9c5100caf0f84e22d88451e94ce2bb';

// const md = markdownit({ html: true, breaks: true, });

// 先创建基础实例
const baseMd = markdownit({ html: true, breaks: true });

let first = true;
// 重新初始化并扩展配置
const md = markdownit({
    ...baseMd.options, // 继承原有配置
    highlight: (str: string, lang: string) => {
        if (lang && hljs.getLanguage(lang)) {
            try {
                return `<pre class="hljs sql-block"><code>${
                    hljs.highlight(str, {
                        language: lang,
                        ignoreIllegals: true
                    }).value
                    }</code></pre>`;
            } catch (__) { }
        }
        // 使用基础实例的方法进行转义
        return `<pre class="hljs"><code>${baseMd.utils.escapeHtml(str)}</code></pre>`;
    }
});

const defaultConversationsItems = [
    {
        key: JSON.stringify(generateRandomNumber()),
        label: '梧桐数据分析大模型'
    }
];

// 切换大模式
const options = [
    {
        value: 'chatbi-turbo',
        label: 'Analyst-turbo',
        desc: '快速生成数据查询及可视化'
    },
    {
        value: 'chatbi-o1',
        label: 'Analyst-o1',
        desc: '具备先进的深度思考能力'
    },

    {
        value: 'chatbi-pro',
        label: 'Analyst-pro',
        desc: '专业的数据分析专家'
    },
    {
        value: 'data-manus',
        label: 'DataManus',
        desc: '强大的思考、规划与执行能力'
    }
];
let client = new OpenAI({
    baseURL: '',
    apiKey: '',
    dangerouslyAllowBrowser: true
});
let base64 = '';
let modelName = 'chatbi-turbo';
// 试用uuid生成sourseKey2
let sourseKey2 = uuidv4(); 
let currentSourceId = '';
let currentSourceName = '';
const Home = () => {    
    const location = useLocation();
    const [displayText, setDisplayText] = useState('选择来源');
    
    // 添加状态变量用于存储HTML和代码内容
    const [htmlContent, setHtmlContent] = useState('');
    const [startSearch, setStartSearch] = useState(false);
    const [codeContent, setCodeContent] = useState('');
    const [fileContent, setFileContent] = useState('');
    const [currentFilePath, setCurrentFilePath] = useState('');
    
    // 添加文件列表状态
    const [fileList, setFileList] = useState<any[]>([]);
    const [fileListLoading, setFileListLoading] = useState(false);
    const [fileListError, setFileListError] = useState<string | null>(null);
    
    // 文件轮询相关的ref
    const filePollingRef = useRef(null);
    const isFilePollingActiveRef = useRef(false);
    
    // 添加状态变量用于管理左右布局的宽度
    const [leftPanelWidth, setLeftPanelWidth] = useState(100); // 默认左侧占70%
    const [isDragging, setIsDragging] = useState(false);
    
    // 添加可拖动分隔线组件
    const DraggableDivider = () => {
        const isDraggingRef = useRef(false);
        
        const handleMouseDown = (e: React.MouseEvent) => {
            isDraggingRef.current = true;
            setIsDragging(true);
            
            const handleMouseMove = (e: MouseEvent) => {
                if (isDraggingRef.current) {
                    const container = document.querySelector('.chatBI');
                    if (container) {
                        const containerRect = container.getBoundingClientRect();
                        const newLeftWidth = ((e.clientX - containerRect.left) / containerRect.width) * 100;
                        // 限制最小宽度
                        if (newLeftWidth >= 30 && newLeftWidth <= 85) {
                            setLeftPanelWidth(newLeftWidth);
                        }
                    }
                }
            };

            const handleMouseUp = () => {
                isDraggingRef.current = false;
                setIsDragging(false);
                document.removeEventListener('mousemove', handleMouseMove);
                document.removeEventListener('mouseup', handleMouseUp);
            };
            
            document.addEventListener('mousemove', handleMouseMove);
            document.addEventListener('mouseup', handleMouseUp);
        };

        return (
            <div 
                className="divider"
                onMouseDown={handleMouseDown}
                style={{
                    width: '4px',
                    cursor: 'col-resize',
                    background: '#f0f0f0',
                    height: '100%',
                    zIndex: 10,
                    position: 'relative',
                    transition: isDragging ? 'none' : 'background 0.3s',
                }}
            >
                <div 
                    style={{
                        position: 'absolute',
                        top: '50%',
                        left: '50%',
                        transform: 'translate(-50%, -50%)',
                        width: '4px',
                        height: '30px',
                        background: '#d9d9d9',
                        borderRadius: '2px',
                    }}
                />
            </div>
        );
    };
    // 添加在其他工具函数附近，例如在useEffect之前
    const convertFileToBase64 = (file: File): Promise<string> => {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = () => {
                // 移除data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,前缀
                const base64String = reader.result as string;
                const base64Content = base64String.split(',')[1];
                resolve(base64Content);
            };
            reader.onerror = error => reject(error);
        });
    };


    // 处理会话切换
    useEffect(() => {
        const conversationKey = location.state?.conversationKey;
        const isNew = location.state?.isNew;

        if (conversationKey) {
            // 更新当前活动的会话key
            setActiveKey(conversationKey);

            if (!isNew) {
                // 保存当前会话状态到历史
                setConversationHistory(prev => ({
                    ...prev,
                    [activeKey]: {
                        messages,
                        sourceKey: currentSelectedSource.key,
                        modelName,
                        attachedFiles
                    }
                }));
            }

            // 恢复目标会话状态
            const targetConversation = conversationHistory[conversationKey];
            if (targetConversation) {
                setMessages(targetConversation.messages);
                modelName = targetConversation.modelName;
                setAttachedFiles(targetConversation.attachedFiles || []);
            } else {
                // 新会话初始化
                setMessages([]);
                setAttachedFiles([]);
                // 可能需要重置会话ID
                sourseKey2 = uuidv4();
            }
        }
    }, [location.state]);
    // ==================== State ====================
    const [conversationHistory, setConversationHistory] = useState<{
        [key: string]: {
            messages: any[];
            sourceKey: string;
            modelName: string;
            attachedFiles: any[];
        };
    }>({});
    // ==================== State ====================
    // 状态管理
    const PlanRenderer = ({
        content,
        type,
        planId,
        onClick
    }: {
        content: string;
        type: 'title' | 'content';
        planId: number;
        onClick?: (planId: number) => void;
    }) => {
        if (type === 'title') {
            return (
                <div
                    className="plan-title"
                    // onClick={() => onClick ?.(planId){}}
                    onClick={() => {
                        setLocalShow(true);
                        setAutoShowPanel(true);
                    }}
                    style={{
                        cursor: 'pointer',
                        margin: '8px 0',
                        transition: 'all 0.3s',
                    }}
                >
                    <Space className="bianzu">
                        <img src={bianzu} className="icon" />
                        <span>{content}</span>
                    </Space>
                </div>
            );
        }

        return (
            <div className="plan-content">
                <div dangerouslySetInnerHTML={{ __html: md.render(content) }} />
            </div>
        );
    };
    // 来源弹窗跳转
    const [openRole, setOpenRole] = React.useState(false);
    const [confirmLoadingRole, setConfirmLoadingRole] = React.useState(false);
    const [selectedSource, setSelectedSource] = React.useState<any | null>(null); // 存储子组件传来的 ID
    const [currentSelectedSource, setcurrentSelectedSource] = React.useState<any | null>(null); // 存储子组件传来的 ID
    const handleOkRole = () => {
        setConfirmLoadingRole(true);
        setTimeout(() => {
            setOpenRole(false);
            setConfirmLoadingRole(false);
        }, 2000);
        if (!selectedSource?.key) {
            alert('请先选择来源');
            return;
        }
        setcurrentSelectedSource(selectedSource);
        currentSourceId = selectedSource?.key;
        currentSourceName = selectedSource?.label;
        setOpenRole(false);
    };

    const handleCancelRole = () => {
        setOpenRole(false);
    };

    useEffect(() => {
        if (!currentSelectedSource?.key) {
            return;
        }
        currentSelectedSource?.label
            ? setDisplayText(`来源: ${currentSelectedSource?.label}`)
            : setDisplayText('选择来源');
    }, [currentSelectedSource]); // sourceId 变化时重新获取数据


    const [divHeight, setDivHeight] = React.useState<number>(0);
    const divRef = React.useRef<HTMLDivElement>(null);

    // 获取页面高度
    const getPageHeight = (): number => {
        return Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
    };

    // 调整 div 高度
    const adjustDivHeight = () => {
        const pageHeight = getPageHeight();
        const newHeight = pageHeight - 210;
        if (newHeight > 0) {
            setDivHeight(newHeight);
        } else {
            setDivHeight(0);
        }
    };

    // 监听窗口大小变化
    useEffect(() => {
        if (divRef.current) {
            adjustDivHeight(); // 页面加载时初始化高度
            window.addEventListener('resize', adjustDivHeight);

            // 清理事件监听器
            return () => {
                window.removeEventListener('resize', adjustDivHeight);
            };
        }
    }, []);

    // 监听窗口大小变化事件
    window.addEventListener('resize', adjustDivHeight);

    // 页面加载时也执行一次，确保初始高度正确
    window.addEventListener('load', adjustDivHeight);
    // 在组件中

    const [attachedFiles, setAttachedFiles] = useState<AttachedFile[]>([]);
    const [headerOpen, setHeaderOpen] = React.useState(false);
    const [content, setContent] = React.useState('');
    const [conversationsItems, setConversationsItems] = React.useState(defaultConversationsItems);
    const [activeKey, setActiveKey] = React.useState(defaultConversationsItems[0].key);
    // const [attachedFiles, setAttachedFiles] = React.useState([]);
    const [attachedFilesNew, setAttachedFilesNew] = React.useState<any>({});
    const [searchLoading, setSearchLoading] = React.useState(false);
    const abortRef = React.useRef(false); // 创建一个 ref 来存储中断标志
    const [canvasLoading, setCanvasLoading] = React.useState<boolean>(false);

    // 添加 ref
    const attachmentsRef = React.useRef<any>(null);
    const senderRef = React.useRef<any>(null);

    const [apikey, setApikey] = React.useState('empty');
    const [baseUrl, setBaseUrl] = React.useState(window.config.API_BASE_URL + '/chatbiv3');
    const [selectedValue, setSelectedValue] = useState<string>('chatbi-turbo');

    // 左侧下拉菜单
    const handleChange = (value: string) => {
        // 根据选中的 value 查找对应的选项
        const selectedOption = options.find(opt => opt.value === value);
        if (selectedOption) {
            const { label } = selectedOption;
            setSelectedValue(value);
            messageApi.open({
                type: 'success',
                content: '模式已切换至' + label,
            });
            setApikey('empty');
            setBaseUrl(window.config.API_BASE_URL + '/chatbiv3');
            modelName = value;
        }
    };
    useEffect(() => {
        client = new OpenAI({
            baseURL: baseUrl,
            apiKey: apikey,
            dangerouslyAllowBrowser: true,
            defaultHeaders: generateHeadersChat(
                COMMON_APPID,
                'chatbiv3/chat/completions', // capabilityname
                COMMON_APPKEY
            )
        });
    }, [apikey, baseUrl]);
    // ==================== Runtime ====================

    useEffect(() => {
        // if (activeKey !== undefined) {
        //     setMessages([...messages]);
        // }
        setMessages([]);
    }, [activeKey]);
    // ==================== Event ====================
    // 全局提示
    const [messageApi, contextHolder] = message.useMessage();
    const onSubmit = async (nextContent: any) => {
        if (!nextContent) {
        } else {
            if (attachedFiles.length > 0) {
                // 检查文件类型
                attachedFiles.map((item: any) => {
                    // 检查文件类型
                    const file = (item as unknown as { originFileObj: File }).originFileObj;
                    const suffix = file.name.substr(file.name.lastIndexOf('.'));
                    if (suffix !== '.xls' && suffix !== '.xlsx') {
                        messageApi.open({
                            type: 'warning',
                            content: '仅能处理Excel'
                        });
                        return false;
                    }
                })

                // 转换文件为base64
                try {
                    let files: Array<any> = [];
                    const promises = attachedFiles.map(async (item: any) => {
                        // 检查文件类型
                        const file = (item as unknown as { originFileObj: File }).originFileObj;
                        let filename = file.name;
                        const base64Content = await convertFileToBase64(file);
                        return {
                            content: base64Content,
                            role: filename,
                            source: '',
                            session_id: sourseKey2
                        };
                    });
                    
                    // 等待所有文件处理完成
                    files = await Promise.all(promises);
                    
                    // 创建用户消息
                    const userMessage = {
                        role: 'user',
                        content: nextContent,
                        session_id: sourseKey2,
                    };
                    
                    // 保存文件信息到UI显示
                    setAttachedFilesNew({
                        [messages.length]: {
                            files: attachedFiles,
                            tip: '已上传Excel文件'
                        },
                        ...attachedFilesNew
                    });
                    const multiMessage = {
                        message: nextContent,
                        files: files,
                    }
                    // 现在files数组已包含所有处理好的文件
                    onRequest(JSON.stringify(multiMessage))
                    setContent('');
                    setHeaderOpen(false);
                    setAttachedFiles([]);
                }
                catch (error) {
                    messageApi.open({
                        type: 'error',
                        content: '文件处理失败'
                    });
                }
            } else {
                const multiMessage = {
                    message: nextContent,
                    files: [],
                }
                onRequest(JSON.stringify(multiMessage))
                setContent('');
                setHeaderOpen(false);
            }
        }
    };
    // 流式处理改造
const [agent] = useXAgent({
    request: async (info, callbacks: any) => {
        const { message, messages } = info;
        const { onSuccess, onUpdate, onError } = callbacks;
        const chatList = [];
        if(agentLoading) {
            messageApi.open({
                type: 'warning',
                content: '请等待上一个问题回答完成'
            })
            return
        }
        agentLoading = true;
        // 添加防抖函数
        let lastUpdateTime = 0;
        const debouncedUpdate = (list: any[]) => {
            const now = Date.now();
            if (now - lastUpdateTime >= 100) { // 每秒最多更新一次
                lastUpdateTime = now;
                onUpdate([...list]); // 创建新数组避免引用问题
            }
        };

        startFilePolling();
        // 添加默认等待回复
        const loadingMessage = [{ content: "正在处理您的请求，请稍候", content_type: "loading" }];
        onUpdate(loadingMessage);
        // 设置超时检测
        let responseTimeout: NodeJS.Timeout | null = setTimeout(() => {
            onUpdate([{ content: "我正在努力处理您的请求，可能需要一点时间，请耐心等待", content_type: "loading" }]);
        }, 5000); // 5秒后更新等待消息
        if (message == '') {
            onSuccess('');
            if (responseTimeout) clearTimeout(responseTimeout);
        } else {
            try {
                // 确保message不为undefined再进行解析
                let messagesStr = message ? JSON.parse(message) : { message: '', files: [] };
                
                // 立即启动文件查询和显示右侧面板
                setStartSearch(true);
                setLeftPanelWidth(70);
                setAutoShowPanel(true);
                
                const stream = await client!.chat.completions.create({
                    model: modelName,
                    messages: [
                        {
                            role: 'user',
                            content: `${messagesStr.message}`
                        } as any,
                        ...messagesStr.files

                    ],
                    user: 'tiantian',
                    stream: true,
                    source_id: currentSourceId,
                    // source: currentSourceName,  // 这里使用了 source 参数
                    cache: false,
                    session_id: sourseKey2,
                });

                // 清除超时检测
                if (responseTimeout) {
                    clearTimeout(responseTimeout);
                    responseTimeout = null;
                }

                let buffer = '';
                let currentType: ContentType = 'text';

                for await (const chunk of stream) {
                    if (abortRef.current) break;
                    const delta = chunk.choices[0] ?.delta as { content?: string; content_type?: ContentType };
                    const chunkContent = delta ?.content || '';
                    const chunkType = delta ?.content_type || 'text';
                    
                    // 类型切换处理
                    if (chunkType !== currentType) {
                        if (buffer) {
                            chatList.push({ content: buffer, content_type: currentType });
                            onUpdate(chatList);
                            buffer = '';
                        }
                        currentType = chunkType;
                    }

                    buffer += chunkContent;
                    
                    // 实时更新（根据实际需求调整触发频率）
                    // if (!chatList.length) {
                    //     chatList.push({ content: buffer, content_type: currentType });
                    // } else {
                    //     chatList.pop();
                    //     chatList.push({ content: buffer, content_type: currentType });
                    // }
                    // 单独处理HTML和代码内容进行流式输出
                    // 根据内容类型决定渲染位置
                    if (['loading', 'warn', 'think', 'mcp', 'status'].includes(currentType)) {
                        // 这些类型的内容添加到chatList并在左侧渲染
                        if (chunkContent) { // 只有当有内容时才添加
                            chatList.pop();
                            chatList.push({ content: buffer, content_type: chunkType });
                        }
                    } else {
                        // 其他类型的内容（html、code、text、status等）更新到右侧面板
                        setCodeContent(buffer);
                    }
                    // 使用防抖函数进行更新
                    debouncedUpdate(chatList);
                    // onUpdate(chatList);
                }
                onSuccess(chatList);
                base64 = '';
            } catch (error) {
                // 清除超时检测
                if (responseTimeout) {
                    clearTimeout(responseTimeout);
                    responseTimeout = null;
                }
                // 错误时停止文件查询
                setStartSearch(false);
                // 显示错误提示
                
                // 调用onError以便上层组件可以处理错误
                // onError(error);
                // agentLoading = false;
                onUpdate([{ 
                    content: "抱歉，处理您的请求时遇到了问题。请稍后再试或尝试重新提问。", 
                    content_type: "warn" 
                }]);

            }
            finally {
                stopFilePolling()
                // 会话结束时停止文件查询
                setStartSearch(false);
            }
        }
    }
});

    const { onRequest, messages, setMessages } = useXChat({
        agent
    });

    // 暂停输出
    const handleAbort = () => {
        // agentLoading = false;
        abortRef.current = true;
    };

    const onPromptsItemClick = (info: any) => {
        if (info.data.key == '1') {
            setOpenRole(true);
        } else {
            onRequest(info.data.description);
        }
    };
    const handleFileChange = (info: any) => {
        setAttachedFiles(info.fileList);
    };
    // 添加复制功能
    const handleCopy = (content: string) => {
        navigator.clipboard.writeText(content);
    };

    // 添加重新生成功能
    const handleRegenerate = (message: string) => {
        if (message) {
            onRequest(message);
        }
    };

    // 画笔功能
    const [drawMode, setDrawMode] = React.useState(false);
    const toggleDrawBtn = (info: any, elClass: string, type: string, elClassBtn: string) => {
        setDrawMode(true);
        canvasDrawing(info, document.querySelector('.' + elClass), type, document.querySelector('.' + elClassBtn));
    };
    const saveBtn = (info: any, elClass: string, type: string) => {
        const canvas = document.querySelector('.' + elClass);
        if (canvas instanceof HTMLCanvasElement) {
            var imageData = canvas.toDataURL('image/png');
            // 找到 <chart> 的位置
            const start = info.message.indexOf('<chart>') + '<chart>'.length;
            const end = info.message.indexOf('</chart>', start);

            // 截取内容
            const chartContent = info.message.slice(start, end);
            setCanvasLoading(true);
            setTimeout(() => {
                setCanvasLoading(false);
            }, 1000);
        } else {
        }
        // canvasDrawing(document.querySelector('.' + elClass), type);
    };
    const clearBtn = (info: any, elClass: string, type: string) => {
        canvasDrawing(info, document.querySelector('.' + elClass), type, '');
    };
    // ==================== Nodes ====================

    // 首先定义Excel文件类型白名单
    const EXCEL_MIME_TYPE = [
        'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // .xlsx
        'application/vnd.ms-excel' // .xls
    ];
    // 首页卡片
    const placeholderNode = (
        <Space direction="vertical" size={16} className="placeholder">
            <div className="container">
                <h1>Hello, 我是梧桐数据分析智能体</h1>
                <p className="intro">您在数据分析领域的原⽣数据助理，<br />我可以帮您高效地实现NL2SQL、
                    数据问答、数据分析、数据洞察等多维度的⼤模型智能分析应⽤</p>
                <div className="cards-container">
                    <div className="card-column">
                        <div className="card" onClick={() => handleChange('data-manus')}>
                            <div className="card-content">
                            </div>
                        </div>
                    </div>
                    <div className="card-column">
                        <div className="card" onClick={() => {
                            // 设置文本内容
                            setContent("暑期广州热门航线客座率、票价的波动情况？");

                            // 创建新文件对象
                            // const newFile = {
                            //     uid: `excel-${Date.now()}`,
                            //     name: "大数据分析报告.xlsx",
                            //     status: "done" as const,  // 明确指定为字面量类型
                            //     type: EXCEL_MIME_TYPE[0]
                            // };

                            // // 正确更新数组：将新文件添加到数组中
                            // setAttachedFiles(prevFiles => [...prevFiles, newFile]);

                            // // 展开附件面板
                            // setHeaderOpen(true);
                        }}>
                            <div className="card-content">
                                <h3>智能问答</h3>
                                <p>暑期广州热门航线客座率、票价的波动情况？
                                    <br />
                                    <br />
                                </p>
                                {/* 新增文件展示 */}
                                {/* <div style={{ display: 'flex', alignItems: 'center', gap: 8, margin: 15 }}>
                                    <FileExcelTwoTone />
                                    <span style={{ fontSize: 12 }}>大数据分析报告.xlsx</span>
                                </div> */}
                            </div>
                        </div>
                        <div className="card"
                            onClick={() => {
                                // 设置文本内容
                                setContent("预测未来6个月的客座率趋势");

                                // 创建新文件对象
                                // const newFile = {
                                //     uid: `excel-${Date.now()}`,
                                //     name: "大数据分析报告.xlsx",
                                //     status: "done" as const,  // 明确指定为字面量类型
                                //     type: EXCEL_MIME_TYPE[0]
                                // };

                                // // 正确更新数组：将新文件添加到数组中
                                // setAttachedFiles(prevFiles => [...prevFiles, newFile]);

                            }}>
                            <div className="card-content">
                                <h3>智能分析</h3>
                                <p>预测未来6个月的客座率趋势</p>
                                {/* 新增文件展示 */}
                                {/* <div style={{ display: 'flex', alignItems: 'center', gap: 8, margin: 15 }}>
                                    <FileExcelTwoTone />
                                    <span style={{ fontSize: 12 }}>大数据分析报告.xlsx</span>
                                </div> */}
                            </div>
                        </div>
                    </div>
                    <div className="card-column">
                        <div className="card" onClick={() => {
                            // 设置文本内容
                            setContent("帮我用饼图画出各个产品的市场占有率情况")

                            // 展开附件面板
                            // setHeaderOpen(true);
                        }}>
                            <div className="card-content">
                                <h3>智能图表</h3>
                                <p>帮我用蓝色的折线图展示这个数据</p>
                            </div>
                        </div>
                        <div className="card" onClick={() => {
                            // 设置文本内容
                            setContent("撰写一篇暑期航空市场分析报告");

                            // 创建新文件对象
                            // const newFile = {
                            //     uid: `excel-${Date.now()}`,
                            //     name: "大数据分析报告.xlsx",
                            //     status: "done" as const,  // 明确指定为字面量类型
                            //     type: EXCEL_MIME_TYPE[0]
                            // };

                            // 正确更新数组：将新文件添加到数组中
                            // setAttachedFiles(prevFiles => [...prevFiles, newFile]);

                            // 展开附件面板
                            // setHeaderOpen(true);
                        }}>
                            <div className="card-content">
                                <h3>智能报告</h3>
                                <p>撰写一篇暑期航空市场分析报告</p>
                                {/* 新增文件展示 */}
                                {/* <div style={{ display: 'flex', alignItems: 'center', gap: 8, margin: 15 }}>
                                    <FileExcelTwoTone />
                                    <span style={{ fontSize: 12 }}>大数据分析报告.xlsx</span>
                                </div> */}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </Space>
    );

    const attachmentsNode = (
        <Badge dot={attachedFiles.length > 0 && !headerOpen}>
            <Button type="text" icon={<PaperClipOutlined />} onClick={() => setHeaderOpen(!headerOpen)} />
        </Badge>
    );

    // 上传附件
    const senderHeader = (
        <Sender.Header
            title="附件"
            open={headerOpen}
            onOpenChange={setHeaderOpen}
            styles={{
                content: {
                    padding: 0
                }
            }}
            forceRender
        >
            <Attachments
                ref={attachmentsRef}
                beforeUpload={(file: { type: string; name: { endsWith: (arg0: string) => unknown; }; }) => {
                    // 严格校验文件类型
                    const isExcel = EXCEL_MIME_TYPE.includes(file.type) ||
                        ['.xlsx', '.xls'].some(ext => file.name.endsWith(ext));

                    if (!isExcel) {
                        message.error('仅支持上传Excel文件（.xls, .xlsx）');
                        return Upload.LIST_IGNORE; // 阻止文件添加
                    }
                    return false; // 阻止自动上传
                }}
                items={attachedFiles}
                onChange={handleFileChange}
                placeholder={type =>
                    type === 'drop'
                        ? {
                            title: '上传附件'
                        }
                        : {
                            icon: <CloudUploadOutlined />,
                            title: '上传附件',
                            description: '点击或者拖拽到这里上传'
                        }
                }
                getDropContainer={() => senderRef.current ?.nativeElement}
            />
        </Sender.Header>
    );

    // html
    const [previewMode, setPreviewMode] = useState<'code' | 'preview'>('code');
    // 安全渲染组件
    const SafePreview = ({ html }: { html: string }) => {
        const iframeRef = React.useRef<HTMLIFrameElement>(null);
        const containerRef = React.useRef<HTMLDivElement>(null);

        // Auto-scroll when HTML content changes
        React.useEffect(() => {
            if (containerRef.current) {
                containerRef.current.scrollTop = containerRef.current.scrollHeight;
            }
        }, [html]);

        // Use iframe for safe rendering
        React.useEffect(() => {
            if (!iframeRef.current) return;

            // Create safe document
            const doc = iframeRef.current.contentDocument;
            if (doc) {
                doc.open();
                doc.write(`
                <!DOCTYPE html>
                <html>
                    <head>
                        <base target="_blank">
                            <style>
                                body {margin: 0; padding: 20px; }
                ${DOMPurify.sanitize(html, { WHOLE_DOCUMENT: true })}
                            </style>
                    </head>
                    <body>
                            ${DOMPurify.sanitize(html)}
                    </body>
                </html>
                    `);
                doc.close();
                
                // Scroll iframe content to bottom
                const scrollToBottom = () => {
                    if (doc.body) {
                        doc.body.scrollTop = doc.body.scrollHeight;
                    }
                };
                
                // Apply scrolling after content loads
                setTimeout(scrollToBottom, 100);
            }
        }, [html]);

        return (
            <div ref={containerRef} style={{ height: '100%', overflowY: 'auto' }}>
                <iframe
                    ref={iframeRef}
                    style={{
                        width: '100%',
                        height: 'calc(100vh - 120px)',
                        border: 'none',
                        borderRadius: 8
                    }}
                    sandbox="allow-scripts allow-same-origin"
                />
            </div>
        );
    };

    const showDrawer = () => {
        setLeftPanelWidth(70);
        setLocalShow(true);
        setAutoShowPanel(true);
    };

    const [expandedThink, setExpandedThink] = useState(true);
    const [expandedChart, setExpandedChart] = useState(true);
    const [expandedMcp, setExpandedMcp] = useState(true);
    const [expandedStatus, setExpandedStatus] = useState(true);
const useStyles = () => (
    {
        containerThink: css({
            position: 'relative',
            margin: '16px 0',
            border: '[0.5px] solid',
            borderColor: 'var(--coz-stroke-primary, #e5e7eb)',
            borderRadius: '16px',
            maxWidth: '100%',
            overflow: 'hidden'
        }),
        containerChart: css({
            position: 'relative',
            margin: '16px 0',
        }),
        containerStatus: css({
            whiteSpace: 'wrap',
            padding: '5px'
        }),
        headerThink: css({
            width: '100%',
            height: 'auto',
            display: 'flex',
            alignItems: 'center',
            padding: '6px 10px',
            background: 'transparent',
            borderRadius: 0,
            cursor: 'pointer',
            transition: 'all 0.2s',
            borderBottom: expandedThink ? '[0.5px] solid var(--coz-stroke-primary, #e5e7eb)' : 'none'
        }),
        headerChart: css({
            // width: 130,
            height: 32,
            display: 'flex',
            alignItems: 'center',
            background: '#f5f5f5',
            borderRadius: 8,
            cursor: 'pointer',
            transition: 'all 0.2s',
            marginBottom: 10,
            padding: '0 10px'
        }),
        contentThink: (expanded: boolean) =>
            css({
                overflow: 'hidden',
                marginTop: '10px',
                transition: 'all 0.3s ease-in-out',
                maxHeight: expanded ? '1000px' : 0,
                padding: expanded ? '0px 10px' : 0
            }),
        contentChart: (expanded: boolean) =>
            css({
                overflow: 'hidden',
                transition: 'all 0.3s ease-in-out',
                maxHeight: expanded ? '1000px' : 0,
            }),
        arrowThink: (expanded: boolean) =>
            css({
                marginRight: '20px',
                transition: 'transform 0.2s',
                transform: `rotate(${expanded ? 180 : 0}deg)`,
                color: '#666'
            }),
        arrowChart: (expanded: boolean) =>
            css({
                marginRight: '20px',
                transition: 'transform 0.2s',
                transform: `rotate(${expanded ? 90 : 0}deg)`,
                color: '#666'
            })
    });
    const styles = useStyles();
    // 创建内容渲染器映射
    const CONTENT_RENDERERS: Record<ContentType, (content: string, meta?: any) => JSX.Element> = {
        html: content => (
            <div></div>
        ),
        // content => (
        //     <div className="html-container" onClick={showDrawer}>
        //         <div className="html-header">
        //             <Html5Outlined />
        //             <div>
        //                 <span>basic-html</span>
        //                 <span>基础 HTML 页面</span>
        //             </div>
        //         </div>
        //         <Divider style={{ margin: '5px 0' }} />
        //         <div className="html-bottom">
        //             <ChromeFilled />
        //             <p>生成html</p>
        //         </div>
        //     </div>
        // ),
        loading: content => (
            <div className="loading-container">
                <span>{content}</span>
                <div className="loading-dots">
                    <span className="dot dot1"></span>
                    <span className="dot dot2"></span>
                    <span className="dot dot3"></span>
                </div>
            </div>
        ),
        // text: content =>
        //     <div className="html-content-inner" >
        //         <div dangerouslySetInnerHTML={{ __html: md.render(content) }} />
        //     </div>,

        // <div className="text-content">{content}</div>,

        status: content => {
            // Parse the content to remove HTML tags
            const parser = new DOMParser();
            const doc = parser.parseFromString(content, 'text/html');
            const textContent = doc.body.textContent || '';

            return (
                <div className='container-status'>
                    <div className={styles.containerStatus} onClick={() => setExpandedStatus(!expandedStatus)}>
                        <div style={{ display: 'flex', alignItems: 'center', flex: 1 }}>
                            <img src={thinkingIcon} alt="MCP" width="16" height="16" style={{ marginRight: '8px' }} />
                            <div className="think-title" style={{ marginLeft: '8px', fontWeight: 'normal' }}>{textContent}</div>
                        </div>
                    </div>
                </div>
            );
        },
        sql: content => (
            <div></div>
        ),
        //     (
        //     <pre className="hljs sql-block">
        //         <code>{content}</code>
        //     </pre>
        // ),
        image: content => (
            <div></div>
        ),
        // content => <img src={content} alt="生成图表" className="inline-image" onError={e => (e.currentTarget.style.display = 'none')} />,
        // chart: content => {
        //     try {
        //         const option = JSON.parse(content);
        //         return <div className={styles.containerChart}>
        //             <div className={styles.headerChart} onClick={() => setExpandedChart(!expandedChart)}>
        //                 <CheckCircleFilled style={{ color: '#1677ff' }} />
        //                 <div style={{
        //                     marginLeft: 10
        //                 }}>数据可视化</div>
        //                 <CaretRightOutlined className={styles.arrowChart(expandedChart)} style={{
        //                     width: 12,
        //                     height: 12,
        //                     marginLeft: 10
        //                 }} />
        //             </div>
        //             <div className={styles.contentChart(expandedChart)}>
        //                 <ReactECharts option={option} style={{ width: '100%', height: 300 }} />
        //             </div>
        //         </div>
        //     } catch {
        //         return <div className="chart-error">图表数据解析失败</div>;
        //     }
        // },
        table: content => (
            <div></div>
        ),
        // content =>
        //     <div className="html-content-inner" >
        //         <div dangerouslySetInnerHTML={{ __html: md.render(content) }} />
        //     </div>,
        think: content => (
            <div className='container-think'>
                <div className={styles.headerThink} onClick={() => setExpandedThink(!expandedThink)}>
                    <div style={{ display: 'flex', alignItems: 'center', flex: 1 }}>
                        <img src={thinkingIcon} alt="思考" width="16" height="16" style={{ marginRight: '8px' }} />
                        <div className="think-title" style={{ marginLeft: '8px', fontWeight: 'normal' }}>思考过程</div>
                    </div>
                    <img 
                        src={chevronDown} 
                        alt="展开" 
                        width="16" 
                        height="16" 
                        className={styles.arrowThink(expandedThink)} 
                    />
                </div>
                <div className={styles.contentThink(expandedThink)}>
                    <div
                        style={{
                            borderRadius: 4,
                            padding: '12px 0',
                        }}
                        dangerouslySetInnerHTML={{ __html: md.render(content) }}
                    />
                </div>
            </div>
        ),
        mcp: content => {
            // Parse the content to remove HTML tags
            const parser = new DOMParser();
            const doc = parser.parseFromString(content, 'text/html');
            const textContent = doc.body.textContent || '';

            return (
                <div className='container-think'>
                    <div className={styles.headerThink} onClick={() => setExpandedMcp(!expandedMcp)}>
                        <div style={{ display: 'flex', alignItems: 'center', flex: 1 }}>
                            <img src={thinkingIcon} alt="MCP" width="16" height="16" style={{ marginRight: '8px' }} />
                            <div className="think-title" style={{ marginLeft: '8px', fontWeight: 'normal' }}>正在调用MCP Agent</div>
                        </div>
                        <img 
                            src={chevronDown} 
                            alt="展开" 
                            width="24" 
                            height="24" 
                            className={styles.arrowThink(expandedMcp)} 
                        />
                    </div>
                    <div className={styles.contentThink(expandedMcp)}>
                        <div
                            style={{
                                borderRadius: 4,
                                padding: '0 0 12px 0',
                            }}
                        >
                            {textContent}
                        </div>
                    </div>
                </div>
            );
        },
        ['status@planing']: content =>
            <div className="plan">
                <span className="text">{content}</span>
                <img src={loading} className="icon" />
            </div>,
        // 使用类型断言处理动态类型
        ['plan@title' as ContentType]: (content: any, planId: any) => (
            <PlanRenderer content={content} type="title" planId={planId} />
        ),
        ['plan@content' as ContentType]: (content: any, planId: any) => (
            <PlanRenderer content={content} type="content" planId={planId} />
        )
    };

    const [localShow, setLocalShow] = useState(true);

    
    // 获取文件列表的函数
    const fetchFileList = useCallback(async () => {
        setFileListLoading(true);
        setFileListError(null);
        
        try {
            const response = await fetch(window.config.API_BASE_URL + '/chatbiv3/sandbox', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                    ...generateHeaders(COMMON_APPID, 'chatbiv3/sandbox', COMMON_APPKEY)
                },
                body: JSON.stringify({
                    source_id: currentSourceId || '',
                    session_id: sourseKey2 || '',
                    file_name: null
                })
            });
            
            const result = await response.json();
            if (result && result.file_list) {
                // 直接使用扁平的文件列表
                setFileList(result.file_list);
            } else {
                setFileList([]);
            }
        } catch (error) {
            setFileListError('获取文件目录失败');
        } finally {
            setFileListLoading(false);
        }
    }, [startSearch, fileListLoading]);
    
    // 启动文件轮询
    const startFilePolling = useCallback(() => {
        // if (isFilePollingActiveRef.current) return;
        
        isFilePollingActiveRef.current = true;
        // console.log('启动文件轮询');
        
        // 立即执行一次
        fetchFileList();
        
        // 设置5秒轮询
        filePollingRef.current = setInterval(() => {
            fetchFileList();
        }, 5000);
    }, [fetchFileList, startSearch]);
    
    // 停止文件轮询
    const stopFilePolling = useCallback(() => {
        if (filePollingRef.current) {
            clearInterval(filePollingRef.current);
            filePollingRef.current = null;
        }
        isFilePollingActiveRef.current = false;
        console.log('停止文件轮询');
    }, []);
    
    
    // 组件卸载时清理
    useEffect(() => {
        return () => {
            stopFilePolling();
        };
    }, [stopFilePolling]);
    
    // 处理文件选择的函数
    const handleFileSelect = useCallback(async (content: string, filePath: string) => {
        setCurrentFilePath(filePath);
        
        // 检查文件扩展名，如果是markdown文件则进行渲染
        const isMarkdownFile = filePath.toLowerCase().endsWith('.md') || 
                              filePath.toLowerCase().endsWith('.markdown');
        
        if (isMarkdownFile) {
            // 使用现有的md实例渲染markdown内容
            const renderedContent = md.render(content);
            setPreviewMode('filePrew')
            setFileContent(content); // 保存原始内容
            setHtmlContent(renderedContent); // 保存渲染后的HTML内容
        } else {
            // 普通文本文件直接显示
            setFileContent(content);
            setHtmlContent(content); // 对于非markdown文件，也设置htmlContent以保持一致性
        }
    }, []);

    // 第三步：优化 RightContent 组件
    const RightContent = React.memo(() => {
        const handleClose = useCallback(() => {
            setLeftPanelWidth(100)
            setLocalShow(false);
            setAutoShowPanel(false);
        }, []);
        
        const scrollContainerRef = useRef<HTMLDivElement>(null);
        const [userHasScrolled, setUserHasScrolled] = useState(false);

        const handleScroll = useCallback(() => {
            if (!scrollContainerRef.current) return;
            
            const { scrollTop, scrollHeight, clientHeight } = scrollContainerRef.current;
            const isAtBottom = Math.abs(scrollHeight - scrollTop - clientHeight) < 10;
            
            if (!isAtBottom) {
                setUserHasScrolled(true);
            } else {
                setUserHasScrolled(false);
            }
        }, []);
        
        useEffect(() => {
            const scrollContainer = scrollContainerRef.current;
            if (scrollContainer) {
                scrollContainer.addEventListener('scroll', handleScroll);
                return () => scrollContainer.removeEventListener('scroll', handleScroll);
            }
        }, [handleScroll]);
        
        useEffect(() => {
            if (scrollContainerRef.current && !userHasScrolled) {
                // scrollContainerRef.current.scrollTo({
                //     top: scrollContainerRef.current.scrollHeight,
                //     behavior: 'smooth'
                // });
            }
        }, [htmlContent, codeContent, userHasScrolled]);
        return (
            <div style={{
                height: '100vh',
                width: '100%',
                overflowY: 'auto',
            }}>
                <div
                    style={{
                        padding: 16,
                        fontSize: 18,
                        fontWeight: 'bold',
                        background: '#f5f5f5',
                    }}>
                    <img src={renwu} style={{ width: 16 }} className="icon" />
                    <span style={{ marginBottom: 24, marginLeft: 10 }}>工作空间</span> 
                    <CloseOutlined
                        style={{
                            position: 'absolute',
                            right: 25,
                            top: 20,
                            cursor: 'pointer',
                            color: '#999',
                            fontSize: 22,
                            zIndex: 1,
                        }}
                        onClick={handleClose} />
                </div>
                <div
                    className='right-content-container'
                    style={{
                        padding: 16
                    }}>
                    <Space>
                        <Segmented
                            value={previewMode}
                            onChange={(val: string) => setPreviewMode(val as 'plan' | 'preview' | 'html' | 'code' )}
                            options={[
                                { value: 'code', label: '实时跟随' },
                                { value: 'plan', label: '任务' },
                                { value: 'file', label: '文件' },
                                { value: 'filePrew', label: '文件预览' },
                            ]}
                        />
                    </Space>
                    {previewMode === 'code' ? (
                        <div 
                            className="html-content-container"
                            ref={scrollContainerRef}
                            onScroll={handleScroll}
                        >
                            {codeContent && (
                                <div className="html-content-inner" dangerouslySetInnerHTML={{ __html: md.render(codeContent) }} />
                            )}
                        </div>
                    ) : previewMode === 'plan' ?(
                        <div
                            className="html-content-container"
                            ref={scrollContainerRef}
                            onScroll={handleScroll}
                        >
                            {htmlContent && (
                                <div className="html-content-inner" dangerouslySetInnerHTML={{ __html: md.render(htmlContent) }} />
                            )}
                        </div>
                    ) : previewMode === 'file' ? (
                        <div
                            className="html-content-container file-browser-container"
                            ref={scrollContainerRef}
                            onScroll={handleScroll}
                        >
                            <div className="file-explorer-layout">
                                <FileExplorer 
                                    onSelectFile={handleFileSelect}
                                    sessionId={sourseKey2}
                                    fileList={fileList}
                                    loading={fileListLoading}
                                    error={fileListError}
                                    onRefresh={fetchFileList}
                                />
                                {/* <div className="file-content">
                                    {currentFilePath && (
                                        <div>
                                            <h3>{currentFilePath}</h3>
                                            <div className="file-content-preview">
                                                {currentFilePath.toLowerCase().endsWith('.md') || currentFilePath.toLowerCase().endsWith('.markdown') ? (
                                                    // 显示渲染后的markdown
                                                    <div dangerouslySetInnerHTML={{ __html: htmlContent }} />
                                                ) : (
                                                    // 显示普通文本内容
                                                    <pre style={{ whiteSpace: 'pre-wrap', fontFamily: 'monospace', background: '#f5f5f5', padding: '16px', borderRadius: '4px' }}>
                                                        {fileContent}
                                                    </pre>
                                                )}
                                            </div>
                                        </div>
                                    )}
                                    {!currentFilePath && <div className="empty-state">请选择一个文件查看内容</div>}
                                </div> */}
                            </div>
                        </div>
                    ) : (
                        <div
                            className="html-content-container"
                        >
                            <SafePreview html={DOMPurify.sanitize(htmlContent)} />
                        </div>
                    )}
                </div>
            </div>
        );
    });
    const [autoShowPanel, setAutoShowPanel] = useState(false);
    // 第一步：将渲染函数转换为正式组件
    const MarkdownItem = ({ itemData, index }: { itemData: any; index: number }) => {
        // 确保所有 hooks 在顶层调用
        const { message: content, status } = itemData;
        const processedContent = useMemo(() => {
            try {
                return content;
            } catch {
                return content;
            }
        }, [content]); // 依赖项明确
        // useEffect(() => {
        //     if (typeof processedContent !== 'string') {
        //         const hasSpecialContent = processedContent.some((item: any) =>
        //             /^plan@\d+@content$/.test(item.content_type) ||
        //             item.content_type === 'html'
        //         );
        //         setLeftPanelWidth(hasSpecialContent ? 70 : 100);
        //         setAutoShowPanel(hasSpecialContent);
        //     }
        // }, [processedContent]);
        return (
            <Typography>
                {status === 'local' ? (
                    <LocalContent content={processedContent} index={index} />
                ) : (
                        processedContent.map((item: any) => (
                            <ContentRenderer
                                key={item.id}
                                item={item}
                                index={index}
                                itemData={itemData}
                                onAutoShowChange={setAutoShowPanel}
                            />
                        ))
                    )}
            </Typography>
        );
    };

    // 第二步：创建独立的内容渲染组件
    const ContentRenderer = React.memo(({ item, index, itemData, onAutoShowChange }:
        { item: any, index: number, itemData: any, onAutoShowChange: (show: boolean) => void }
    ) => {
        // console.log("ContentRenderer", item.content_type);
        // 使用 useEffect 处理显示逻辑
        // useEffect(() => {
        //     const shouldShow = /^plan@\d+@content$/.test(item.content_type) ||
        //         item.content_type === 'html';
        //     onAutoShowChange(shouldShow);
        //     // setLocalShow(shouldShow)
        // }, [item.content_type]);

        return <RemoteContent content={item.content} contentType={item.content_type}
            index={index} itemData={itemData} />;
    });

    // 第二步：拆分子组件
    const LocalContent = ({ content, index }: { content: string; index: number }) => (
        <>
            {attachedFilesNew[index] ?.files ?.length > 0 && (
                <Flex vertical gap="middle" style={{ padding: '20px 0' }}>
                    {attachedFilesNew[index].files.map((item: any) => (
                        <Attachments.FileCard key={item.uid} item={item} />
                    ))}
                </Flex>
            )}
            <div dangerouslySetInnerHTML={{ __html: md.render(JSON.parse(content).message) }} />
        </>
    );

    // 第三步：远程内容子组件
    const RemoteContent = ({ content, contentType, index, itemData }: {
        content: string;
        contentType: ContentType;
        index: number;
        itemData: any
    }) => {
        // 解析plan类型
        const planMatch = contentType.match(/^plan@(\d+)@(title|content)$/);

        // 获取渲染器
        const getRenderer = () => {
            if (planMatch) {
                const [, planId, type] = planMatch;
                return type === 'title'
                    ? CONTENT_RENDERERS['plan@title' as ContentType]
                    : CONTENT_RENDERERS['plan@content' as ContentType];
            }
            return CONTENT_RENDERERS[contentType];
        };
        const renderer = getRenderer();
        return (
            <>
                {/* {contentType === 'chart' ? (
                    <Spin tip="魔法画笔绘制中🪄" spinning={canvasLoading}>
                        <div className="canvasDraw">
                            {renderer(content)}
                            <canvas className={`draw${index}`} style={{ position: 'absolute', top: 0, left: 0 }} />
                        </div>
                    </Spin>
                ) : (
                    renderer(content)
                )} */}
                {/* {contentType === 'chart' && (
                    <div style={{ margin: '10px 0' }}>
                        <Flex gap="small" wrap>
                            <Button
                                className={`toggleDrawBtn${index}`}
                                onClick={() => toggleDrawBtn(itemData, `draw${index}`, 'toggleDrawBtn', `toggleDrawBtn${index}`)}
                                color="primary"
                                variant="filled"
                            >
                                开始绘制
                            </Button>
                            <Button onClick={() => saveBtn(itemData, `draw${index}`, 'saveBtn')} color="primary" variant="filled">
                                保存
                            </Button>
                            <Button onClick={() => clearBtn(itemData, `draw${index}`, 'clearBtn')} color="primary" variant="filled">
                                清除
                            </Button>
                        </Flex>
                    </div>
                )} */}
                {
                    planMatch ? (
                        renderer(content, {
                            planId: parseInt(planMatch[1]),
                            type: planMatch[2]
                        })
                    ) : (
                            renderer(content)
                        )}
            </>
        );
    };

    // 输入框上面功能
    const senderPromptsItems = [
        {
            key: '1',
            description: (
                <div className="source-box">
                    <span>{displayText}</span>
                </div>
            ),
            icon: (
                <RocketOutlined
                    style={{
                        color: '#8c8c8c'
                    }}
                />
            )
        },
        {
            key: '2',
            description: '推荐问题',
            icon: (
                <FireOutlined
                    style={{
                        color: '#8c8c8c'
                    }}
                />
            )
        },
        {
            key: '3',
            description: '查看数据',
            icon: (
                <ReadOutlined
                    style={{
                        color: '#8c8c8c'
                    }}
                />
            )
        }
    ];

    // 使用useRef来存储DOM节点引用
    const messageListRef = useRef<HTMLDivElement>(null);

    // 使用useEffect来监听数据变化并更新UI
    useEffect(() => {
        if (messageListRef.current) {
            // 仅在数据变化时更新DOM
            // messageListRef.current.scrollTop = messageListRef.current.scrollHeight;
        }
    }, [messages]);

    // 定义MemoizedBubbleList的props类型
    interface MemoizedBubbleListProps {
        messages: any[];
        localShow: boolean;
        autoShowPanel: boolean;
    }

    // 使用MemoizedBubbleListProps类型
    const MemoizedBubbleList = React.memo(({ messages, localShow, autoShowPanel }: MemoizedBubbleListProps) => (
        <Bubble.List
            style={{ height: headerOpen ? `${divHeight - 100}px` : `${divHeight}px`, maxHeight: headerOpen ? `${divHeight - 100}px` : `${divHeight}px`, margin: '60px 0 0 0' }}
            roles={{
                ai: {
                    placement: 'start',
                    avatar: { icon: <img src={WT_icon} />, style: { background: 'none' } },
                    typing: { step: 5, interval: 20 },
                    style: {
                        marginLeft: localShow && autoShowPanel ? '12px' : '15%',
                        marginRight: localShow && autoShowPanel ? '12px' : '15%',
                        marginTop: 24,
                        width: localShow && autoShowPanel ? '' : '70%',
                        maxWidth: localShow && autoShowPanel ? '' : '70%',
                    }
                },
                user: {
                    placement: 'end',
                    avatar: { icon: <img src={WT_icon} />, style: { background: 'none', display: 'none' } },
                    style: {
                        width: localShow && autoShowPanel ? '' : '30%',
                        marginLeft: localShow && autoShowPanel ? '0%' : '55%',
                        marginRight: localShow && autoShowPanel ? '12px' : '15%',
                    }
                }
            }}
            items={messages.map((item: any, index: number) => {
                const isAI = !!(index % 2);
                return {
                    key: item.id,
                    role: isAI ? 'ai' : 'user',
                    header: isAI ? '梧桐ChatBI' : '',
                    content: <MarkdownItem key={item.id} itemData={item} index={index} />,
                    footer: isAI ? (
                        <Space size={8}>
                            <Button type="text" size="small" icon={<CopyOutlined />} onClick={() => handleCopy(item.message)} />
                            <Button type="text" size="small" icon={<LikeOutlined />} onClick={() => handleCopy(item.message)} />
                            <Button type="text" size="small" icon={<DislikeOutlined />} onClick={() => handleCopy(item.message)} />
                            <Button type="text" size="small" icon={<WarningOutlined />} onClick={() => handleCopy(item.message)} />
                        </Space>
                    ) : (
                        <Space size={8}>
                            <Button type="text" size="small" icon={<SyncOutlined />} onClick={() => handleRegenerate(item.message)} />
                        </Space>
                    )
                };
            })}
        />
    ));

    // ==================== Render =================
    return (
        <div className="chatBI">
            <div className="chat" style={{ display: 'flex', flexDirection: 'row', height: '100vh' }}>
                {/* 左侧消息列表 */}
                <div 
                    style={{
                        width: `${leftPanelWidth}%`,
                        height: '100vh',
                        position: 'relative',
                        transition: isDragging ? 'none' : 'width 0.3s',
                        borderRight: '1px solid #f0f0f0',
                        display: 'flex',
                        flexDirection: 'column'
                    }}
                    className="left-panel"
                >
                    <div className="bgImage" ref={divRef} style={{ flex: 1, overflow: 'auto', position: 'relative' }}>
                        <Select
                            size="large"
                            value={selectedValue}
                            className="select"
                            variant="borderless"
                            onChange={handleChange}
                            optionRender={(option: any) => (
                                <Space>
                                    <div className="optionRender">
                                        <p style={{ margin: '0' }} aria-label={option.data.label}>
                                            {option.data.label}
                                        </p>
                                        <p style={{ margin: '0', fontSize: '12px', color: 'rgba(0,0,0,0.45)' }}>{option.data.desc}</p>
                                    </div>
                                </Space>
                            )}
                            options={options}
                        />

                        <div style={{ paddingBottom: '120px', overflowX: 'hidden' }}>
                            {messages.length == 0 ?
                                placeholderNode
                                :
                                <MemoizedBubbleList messages={messages} localShow={localShow} autoShowPanel={autoShowPanel} />
                            }
                        </div>
                    </div>
                    
                    {/* 输入框 - 固定在底部 */}
                    <div
                        style={{
                            position: 'absolute',
                            bottom: '20px',
                            left: '0',
                            width: '100%',
                            padding: '0 20px'
                        }}
                    >
                        {/* 输入框 */}
                        <div style={{
                            margin: '0 auto',
                            maxWidth: '800px',
                            border: '1px solid #d9d9d9',
                            borderRadius: 8,
                            background: '#fff',
                            position: 'relative'
                        }}>
                            {/* 配置数据行 */}
                            <div style={{
                                borderBottom: headerOpen ? 'none' : '1px solid #f0f0f0',
                                fontSize: 12,
                                color: 'rgba(0, 0, 0, 0.88)',
                                display: headerOpen ? 'none' : 'block'
                            }}>
                                <Prompts items={senderPromptsItems} onItemClick={onPromptsItemClick} />
                            </div>

                            {/* 输入框容器 */}
                            <div style={{ position: 'relative' }} className={messages.length > 0 ? "has-messages" : ""}>
                                <Sender
                                    placeholder="您好，我是您的数据助理，请问有什么可以帮您的吗?"
                                    ref={senderRef}
                                    value={content}
                                    header={senderHeader}
                                    onSubmit={onSubmit}
                                    onChange={setContent}
                                    prefix={attachmentsNode}
                                    loading={agent.isRequesting()}
                                    // loading={agentLoading}
                                    className="adaptive-textarea"
                                    style={{
                                        border: 'none',
                                        boxShadow: 'none',
                                    }}
                                    onPasteFile={file => {
                                        setHeaderOpen(true);
                                        const extension = file.name.split('.').pop()?.toLowerCase();
                                        if (extension && ['xls', 'xlsx'].includes(extension)) {
                                            attachmentsRef.current?.upload(file);
                                            setHeaderOpen(true);
                                        } else {
                                            message.warning('仅支持粘贴Excel文件');
                                        }
                                    }}
                                    onCancel={() => handleAbort()}
                                />
                            </div>
                        </div>
                        <div className="bottom" style={{ 
                            textAlign: 'center', 
                            marginTop: '10px',
                            width: '100%',
                            position: 'static'
                        }}>
                            <p>内容由中国移动九天大模型生成，请仔细核对关键数据。</p>
                        </div>
                    </div>
                </div>
                
                {/* 可拖动分隔线 */}
                {localShow && autoShowPanel && <DraggableDivider />}
                
                {/* 右侧工作台 */}
                {localShow && autoShowPanel && (
                    <div 
                        style={{
                            width: `${100 - leftPanelWidth}%`,
                            height: '100vh',
                            transition: isDragging ? 'none' : 'width 0.3s',
                        }}
                        className="right-panel"
                    >
                        <RightContent />
                    </div>
                )}
                
                <>{contextHolder}</>
                {/* 来源弹窗 */}
                <Modal
                    title="选择来源"
                    width={1200}
                    open={openRole}
                    onOk={handleOkRole}
                    confirmLoading={confirmLoadingRole}
                    onCancel={handleCancelRole}
                    okText="开始对话"
                    cancelText="取消"
                    okButtonProps={{ disabled: !selectedSource?.key }}
                >
                    <ChooseSource onSelect={(item: any) => setSelectedSource(item)} />
                </Modal>
            </div>
        </div>
    );
};

export default Home;
